<?php

class Social_Acl_Role extends Social_Base
{
    public function init()
    {
        $this->setTableName('acl_roles');
        $this->setPrimaryKey('role_id');
    }

    public function addRole($sessionKey, $code, $name, $description)
    {
        // Check permissions
        $user = $this->getUser()->auth($sessionKey);
        if($user['role_code'] != 'admin') {
            throw new InvalidArgumentException('You have no permission to create role');
        }

        // Validate arguments
        $this->_validateCode($code);
        $this->_validateName($name);
        $this->_validateDescription($description);
        if($this->exists(array('code' => $code))) {
            throw new InvalidArgumentException('Role code already exists');
        }

        // Create role
        $currentTime = date('Y-m-d H:i:s');
        $data = array();
        $data['code'] = $code;
        $data['name'] = $name;
        $data['description'] = $description;
        $data['created_at'] = $currentTime;
        $this->insert($data);
    }

    public function addRole($name, $code, $description)
    {
        $currentTime = time();
        $data = array();
        $data['name'] = $name;
        $data['code'] = $code;
        $data['description'] = $description;
        $data['created'] = $currentTime;
        $data['updated'] = $currentTime;
        return $this->insert($data);
    }

    public function editRole($roleId, $name, $code, $description)
    {
        if(empty($roleId)) {
            throw new InvalidArgumentException('Role id required');
        }
        if(empty($name)) {
            throw new InvalidArgumentException('Role name required');
        }
        if(empty($code)) {
            throw new InvalidArgumentException('Role code required');
        }
        if(empty($description)) {
            throw new InvalidArgumentException('Role description required');
        }

        $data = array();
        $data['name'] = $name;
        $data['code'] = $code;
        $data['description'] = $description;
        $data['updated'] = time();
        return $this->updateByPrimary($roleId, $data);
    }

    public function getByCode($roleCode, $fields = array())
    {
        return $this->get(array('code' => $roleCode), $fields);
    }

    /**
     * Get role by role id
     *
     * @param integer $roleId
     * @return array
     */
    public function getRole($roleId)
    {
        return $this->getAdapter()->get($this->_name, array($this->_primary => $roleId));
    }

    /**
     * Add new role
     *
     * @param array $roleData
     * @return integer
     */
    public function addRole($name, $code, $description, $permissions = null)
    {
        // Check permissions
        $user = $this->auth($sessionKey);
        if($user['role_code'] != 'admin') {
            throw new InvalidArgumentException('You have no permission to create role');
        }

        // Validate arguments
        $this->_validateName($name);
        $this->_validateCode($code);
        $this->_validateDescription($description);
        if($this->exists(array('code' => $code))) {
            throw new InvalidArgumentException('Role code already exists');
        }

        // Create role
        $currentTime = date('Y-m-d H:i:s');
        $roleData = array();
        $roleData['name'] = $name;
        $roleData['code'] = $code;
        $roleData['description'] = $description;
        $roleData['created_at'] = $currentTime;

        if(!is_array($permissions) || empty($permissions)) {
            return $this->insert($roleData);
        }

        // Add role permissions
        try {
            $adapter = $this->getAdapter();
            $adapter->beginTransaction();
            $roleId = $this->insert($roleData);

            $permissionData = array();
            $permissionData['role_id'] = $roleId;
            $permissionService = new Social_Acl_Permission();
            foreach($permissions as $permission) {
                $permissionData['resource_id'] = $permission;
                $permissionService->insert($permissionData);
            }
            $adapter->commit();
        } catch (Exception $e) {
            $adapter->rollBack();
            throw $e;
        }
    }

    /**
     * Update role
     *
     * @param integer $roleId
     * @param array $roleData
     * @return void
     */
    public function updateRole($roleId, $name, $code, $description, $permissions = null)
    {
        $roleData = array();
        $roleData['name'] = $name;
        $roleData['code'] = $code;
        $roleData['description'] = $description;

        if(!is_array($permissions) || empty($permissions)) {
            return $this->updateByPrimary($roleId, $roleData);
        }

        // Update role permissions
        try {
            $adapter = $this->getAdapter();
            $adapter->beginTransaction();
            $this->updateByPrimary($roleId, $roleData);

            $permissionService = new Social_Acl_Permission();
            $permissionInfo = $permissionService->find(array('role_id' => $roleId));
            $permissionResources = array();
            foreach($permissionInfo as $permission) {
                $permissionResources[] = $permission['resource_id'];
            }

            // Add permissions
            $addPermissions = array_diff($permissions, $permissionResources);
            $addPermissionData = array();
            foreach($addPermissions as $addPermission) {
                $addPermissionData['role_id'] = $roleId;
                $addPermissionData['resource_id'] = $addPermission;
                $permissionService->insert($addPermissionData);
            }

            // Delete permissions
            $deletePermissions = array_diff($permissionResources, $permissions);
            foreach($deletePermissions as $deletePermission) {
                $permissionService->deleteRolePermission($roleId, $deletePermission);
            }
            $adapter->commit();
        } catch (Exception $e) {
            $adapter->rollBack();
            throw $e;
        }
    }

    /**
     * Delete role
     *
     * @param integer $roleId
     * @param array $deleteAllRelatedData
     * @return void
     */
    public function deleteRole($roleId, $deleteAllRelatedData = null)
    {
        $this->deleteByPrimary($roleId);
    }

    /**
     * List roles
     *
     * @param array $fields
     * @param array $conditions
     * @param integer $pageSize
     * @param integer $pageIndex
     * @return array
     */
    public function listRole($fields = array(), $conditions = array(), $pageIndex = 0, $pageSize = 1000)
    {
        $order = array($this->_primary => 'desc');
        return $this->getAdapter()->find($this->_name, $fields, $conditions, $order, $pageIndex, $pageSize);
    }

    /**
     * Count roles
     *
     * @param array $fields
     * @return integer
     */
    public function countRoles($fields = array())
    {
        return $this->getAdapter()->count($this->_name, $fields);
    }

    private function _validateName($name)
    {
        $this->validate($name, 'name', 'required', null, 'Username required');
        $this->validate($name, 'name', 'minLength', 3, 'Username must be 3 characters more.');
        $this->validate($name, 'name', 'maxLength', 30, 'Username must be 30 characters or less.');
        $this->validate($name, 'name', 'username', null, 'Invalid username(a-zA-Z0-9)');
    }

    public function _validateCode($code)
    {
    
    }

    public function _validateName($name)
    {
    
    }

    public function _validateDescription($description)
    {
    
    }

}
